import 'dart:async';

import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/services.dart';
import 'package:polyv_video_plugin/polyv_utils.dart';

typedef void PolyvLiveVideoPlayerCreatedCallback(
    PolyvLiveController controller);

class PolyvLiveController {
  MethodChannel _channel;

  ///定义一个Controller
  StreamController<Map> _playerStreamController = StreamController<Map>();
  StreamController<Map> _chatStreamController = StreamController<Map>();

  ///获取 StreamSink 做 add 入口
  StreamSink<Map> get _playerSink => _playerStreamController.sink;

  StreamSink<Map> get _chatSink => _chatStreamController.sink;

  ///获取 Stream 用于监听
  Stream<Map> get _playerStream => _playerStreamController.stream;

  Stream<Map> get _chatStream => _chatStreamController.stream;

  ///事件订阅对象
  StreamSubscription _playerSubscription;
  StreamSubscription _chatSubscription;

  PolyvLiveController.init(int id) {
    _channel = new MethodChannel('polyv_live_video_plugin_$id');
    _channel.setMethodCallHandler(_platformCallHandler);
  }

  PolyvLiveController.destroy(int id) {
    _playerSubscription.cancel();
    _playerStreamController.close();
    _chatSubscription.cancel();
    _chatStreamController.close();
    _channel.invokeMethod('destory');
  }

  Future<dynamic> _platformCallHandler(MethodCall call) async {
    if (call.method == "listener") {
      _playerSink.add(call.arguments);
    } else if (call.method == "chatListener") {
      _chatSink.add(call.arguments);
    }
  }

  Future<dynamic> listen(callback(Map arg)) async {
    _playerSubscription = _playerStream.listen((value) {
      ///do change
      callback(value);
    });
  }

  Future<dynamic> setOnChatListener(callback(Map arg)) async {
    await _channel.invokeMethod("setOnChatListener");
    _playerSubscription = _chatStream.listen((value) {
      ///do change
      callback(value);
    });
  }

  Future<void> setVideoURI(String url) {
    assert(url != null);
    return _channel.invokeMethod('setVideoURI', {"url": url});
  }

  Future<void> start() {
    return _channel.invokeMethod('start');
  }

  Future<void> pause() {
    return _channel.invokeMethod('pause');
  }

  Future<void> resume() {
    return _channel.invokeMethod('resume');
  }

  Future<void> stop() {
    return _channel.invokeMethod('stop');
  }

  Future<void> setLivePlay(
      {@required String userId, @required String channelId}) {
    return _channel.invokeMethod(
        'setLivePlay', {"userId": userId, "channelId": channelId});
  }

  Future<bool> isPlaying() {
    return _channel.invokeMethod('isPlaying');
  }

  Future<void> destroy() {
    return _channel.invokeMethod('destroy');
  }

  Future<int> getDuration() {
    return _channel.invokeMethod('duration');
  }

  Future<int> getCurrentPosition() {
    return _channel.invokeMethod('currentPosition');
  }

  Future<int> getBufferPercentage() {
    return _channel.invokeMethod('bufferPercentage');
  }

  Future<int> getBrightness() {
    return _channel.invokeMethod('brightness');
  }

  Future<int> getVolume() {
    return _channel.invokeMethod('volume');
  }

  Future<void> setBrightness(int brightness) {
    return _channel
        .invokeMethod('setBrightness', {"brightness": brightness.toString()});
  }

  Future<void> setVolume(int volume) {
    return _channel.invokeMethod('setVolume', {"volume": volume.toString()});
  }

  Future<void> initDanMu({padding, textSize, textColor}) {
    return _channel.invokeMethod('initDanMu', {
      "padding": padding.toString(),
      "textSize": textSize.toString(),
      "textColor": textColor
    });
  }

  Future<void> sendDanMu(String message) {
    return _channel.invokeMethod('sendDanMu', {"message": message});
  }

  Future<void> showDanMu() {
    return _channel.invokeMethod('showDanMu');
  }

  Future<void> hideDanMu() {
    return _channel.invokeMethod('hideDanMu');
  }

  Future<Object> getChatHistory({
    @required String channelId,
    @required String userId,
    @required String begin,
    @required String end,
  }) async {
    return _channel.invokeMethod('getChatHistory',
        {"channelId": channelId, "userId": userId, "begin": begin, "end": end});
  }

  Future<Object> getChatRoomListUsers({
    @required String channelId,
    @required String userId,
    @required String page,
    @required String length,
  }) async {
    return _channel.invokeMethod('getChatRoomListUsers',
        {"channelId": channelId, "userId": userId, "page": page, "length": length});
  }

  Future<void> sendChatMsg(String message, String courseId, String chapterId) {
    return _channel.invokeMethod('sendChatMsg', {"message": message, "courseId": courseId, "chapterId": chapterId});
  }

  Future<void> initSocket({@required channelId, @required nickName, @required avatar}) {
    return _channel.invokeMethod('initSocket', {
      "channelId": channelId.toString(),
      "nickName": nickName.toString(),
      "avatar": avatar.toString(),
    });
  }

}

class PolyvLivePlayer extends StatefulWidget {
  final PolyvLiveVideoPlayerCreatedCallback onCreated;
  final Set<Factory<OneSequenceGestureRecognizer>> gestureRecognizers;

  PolyvLivePlayer({
    Key key,
    @required this.onCreated,
    this.gestureRecognizers,
  });

  @override
  State<StatefulWidget> createState() => _VideoPlayerState();
}

class _VideoPlayerState extends State<PolyvLivePlayer> {
  @override
  void initState() {
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return defaultTargetPlatform == TargetPlatform.android
        ? AndroidView(
            viewType: 'plugins.polyv/live',
            onPlatformViewCreated: onPlatformViewCreated,
            creationParamsCodec: const StandardMessageCodec(),
          )
        : UiKitView(
            viewType: 'plugins.polyv/live',
            creationParams: <String, dynamic> {
              'appId':PolyvUtils.mAppId,
              'appSecret':PolyvUtils.mAppSecret,
            },
            onPlatformViewCreated: onPlatformViewCreated,
            creationParamsCodec: const StandardMessageCodec(),
          );
  }

  Future<void> onPlatformViewCreated(id) async {
    if (widget.onCreated == null) {
      return;
    }
    widget.onCreated(new PolyvLiveController.init(id));
  }
}
